<template>
  <div class="about">
    <h1>原型</h1>
    <p>
      prototype(原型) 每个函数都有一个隐藏的 [[Prototype]]
      属性，prototype就是原型，用来存储实例公用的属性和方法
    </p>
    <h1>原型链</h1>
    <p>
      Prototype可以通过
      __proto__访问，__proto__指向其原型对象。当访问对象属性时，若对象自身不存在该属性，则会沿着原型链向上查找，直到找到或到达原型链末端（null）。
    </p>

    <h1>__proto__ 和 prototype 的区别?</h1>
    <P>prototype是函数特有的属性，指向该函数的原型对象</P>
    <P>__proto__是每个对象都有的属性，指向其构造函数的原型对象</P>
    <P
      >关系：instance.__proto__ ===
      Constructor.prototype（实例对象通过proto查找其构造函数的原型）</P
    >

    <h1>作用域</h1>

    <p>
      作用域是变量和函数的可访问范围，它决定了代码中哪些部分可以访问特定的标识符（变量名、函数名）。作用域一共有
      4 种：全局作用域，局部作用域、函数作用域以及 eval 作用域。
    </p>

    <h1>作用域链</h1>
    <p>
      作用域链是 JavaScript
      中用于查找变量的一种机制。它由当前作用域和所有父级作用域的变量对象组成。当访问一个变量时，JavaScript
      引擎会首先在当前作用域的变量对象中查找，如果找不到，则会向上一级作用域中查找，直到找到为止，这种向上查找的链路就是作用域链。
    </p>
    <h1>new操作符做了什么</h1>
    <P>在内存中创建一个全新的空对象</P>
    <P>将新对象的 [[Prototype]](即 __proto__)指向构造函数的 prototype 属性</P>
    <P>将构造函数内部的this 绑定到新创建的对象</P>
    <P>如果构造函数返回一个对象，则返回该对象</P>
    <P>如果构造函数返回原始值(或没有返回)，则返回新创建的对象</P>

    <h1>面试官问：Set、Map、WeakSet 和 WeakMap 的区别</h1>
    <P>set:</P>
    <P
      >Set对象允许存储任何类型的唯一值，不允许重复。Set 可以存储任何 JavaScript
      数据类型，包括对象、数组、函数等引用类型。</P
    >
    <P>Set中的值是无序的，无法通过索引访问。</P>
    <P>通过add()方法添加值到Set中，通过has()方法检查值是否存在，通过delete()方法删除值。</P>
    <P>可以使用size属性获取Set中的值的数量。</P>
    <P>Set是迭代器，可以使用forEach()或for...of循环遍历Set中的值。</P>
    <P
      >请注意，Set中存储的值是唯一的，重复的值将被忽略。此外，Set是无序的，无法通过索引进行访问。</P
    >
    <P>————————————————</P>
    <P>&nbsp;</P>
    <P>Map:</P>
    <P>Map对象是键值对的集合，与对象不同的是，键可以是任何数据类型。</P>
    <P>Map中的键值对是有序的。</P>
    <P
      >通过set()方法设置键值对，通过get()方法获取值，通过has()方法检查键是否存在，通过delete()方法删除键值对。</P
    >
    <P>可以使用size属性获取Map中键值对的数量。</P>
    <P>Map也是迭代器，可以使用forEach()或for...of循环遍历键值对。</P>
    <P>Set 和 Map 主要的应用场景在于 数据重组 和 数据储存。</P>

    ---------------------------------------------------
    <P
      >Set 和 Map 是 ES6 引入的两种集合类型，而 WeakSet 和 WeakMap 是它们的弱引用变体。Set
      存储唯一值的集合，无论基本类型还是对象引用，值不可重复且可遍历;Map
      存储键值对，键可以是任意类型(包括对象)，同样可遍历且保留插入顺序。它们都是强引用集合，即使其中的对象不再使用，只要集合存在，垃圾回收器就不会回收这些对象，可能导致内存泄漏。</P
    >
    <P>WeakSet 只能存储对象</P>
    <P>WeakMap 的键必须是对象，值可以是任意类型，常用于存储私有数据或元数据。</P>
    <P
      >WeakSet 只能存储对象引用(不能是基本类型)，且对象是弱引用。如果对象在其他地方被销毁，它在
      WeakSet 中会自动消失，无法阻止垃圾回收。</P
    >
    <P
      >WeakMap
      只接受对象作为键(值可以是任意类型)，键同样是弱引用。当键对象被回收时，关联的键值对会自动移除。</P
    >
    <P>关键特性差异：</P>
    <P
      >弱引用集合不可遍历(没有 keys()、values()
      等方法)，因为其内容随时可能被垃圾回收，无法保证稳定性。</P
    >
    <P>没有 size 属性，同样因内容动态变化无法确定大小。</P>
    <P
      >API 极其有限：WeakSet 只有 add()、has()、delete();WeakMap 只有
      set()、get()、has()、delete()。</P
    >
    <P>设计目的：</P>
    <P>Set/Map 适用于需要存储稳定集合数据的场景(如去重列表、键值映射)。</P>
    <P>WeakSet/WeakMap 专为解决内存泄漏设计。</P>
    <P
      >WeakSet 典型场景：存储对象关联的元数据(如标记已处理过的 DOM
      元素)，元素移除时自动清理标记。</P
    >
    <P
      >WeakMap 典型场景：存储对象的私有属性(Vue3 响应式系统用 WeakMap
      关联对象与依赖)，对象销毁时自动释放关联数据。</P
    >
    <h2>总结：set是（唯一值集合）</h2>
    <h2>‌Map 示例‌（键值对集合）</h2>
    <h2>‌WeakSet 示例‌（对象弱引用集合）仅支持对象类型成员‌：不允许字符串、数字等原始值</h2>
    <h2>
      WeakMap
      示例‌（私有数据存储）:键必须是对象类型‌（包括普通对象、函数、数组等），不支持字符串、数字等基本类型作为键
    </h2>

    <h1>在平常工作中会经常使用到数组，以下是js对数组的常用方法：</h1>
    <p>https://mp.weixin.qq.com/s/INlgjaHseFQwkNYDiM9ySg</p>
    <P>1、forEach() 方法提供了遍历数组元素的其他方法：</P>
    <P
      >const colors = ["red", "green", "blue"];colors.forEach((color) =&gt; console.log(color));//
      red// green// blue</P
    >
    <P
      >传递给 forEach
      的函数对数组中的每个元素执行一次，数组元素作为参数传递给该函数。未赋值的值不会在 forEach
      循环迭代。</P
    >
    <P
      >注意，在数组定义时省略的元素不会在 forEach 遍历时被列出，但是手动赋值为 undefined
      的元素是会被列出的：</P
    >
    <P
      >const sparseArray = ["first", "second", , "fourth"];sparseArray.forEach((element) =&gt; {
      console.log(element);});// first// second// fourthif (sparseArray[2] === undefined) {
      console.log("sparseArray[2] 是 undefined"); // true}const nonsparseArray = ["first", "second",
      undefined, "fourth"];nonsparseArray.forEach((element) =&gt; { console.log(element);});//
      first// second// undefined// fourth</P
    >
    <P
      >由于 JavaScript 元素被保存为标准对象属性，因此不建议使用 for...in 循环遍历 JavaScript
      数组，因为普通元素和所有可枚举属性都将被列出。</P
    >
    <P>2.concat() 方法连接两个或多个数组并返回一个新的数组。</P>
    <P
      >let myArray = ["1", "2", "3"];myArray = myArray.concat("a", "b", "c");// myArray 现在是 ["1",
      "2", "3", "a", "b", "c"]</P
    >
    <P>3.join() 方法将数组中的所有元素连接成一个字符串。</P>
    <P
      >const myArray = ["Wind", "Rain", "Fire"];const list = myArray.join(" - "); // list 现在是
      "Wind - Rain - Fire"</P
    >
    <P>4.push() 方法在数组末尾添加一个或多个元素，并返回数组操作后的 length。</P>
    <P>const myArray = ["1", "2"];myArray.push("3"); // myArray 现在是 ["1", "2", "3"]</P>
    <P>5.pop() 方法从数组移出最后一个元素，并返回该元素。</P>
    <P
      >const myArray = ["1", "2", "3"];const last = myArray.pop();// myArray 现在是 ["1", "2"]，last
      为 "3"</P
    >
    <P>6.shift() 方法从数组移出第一个元素，并返回该元素。</P>
    <P
      >const myArray = ["1", "2", "3"];const first = myArray.shift();// myArray 现在是 ["2",
      "3"]，first 为 "1"</P
    >
    <P>7.unshift() 方法在数组开头添加一个或多个元素，并返回数组的新长度。</P>
    <P
      >const myArray = ["1", "2", "3"];myArray.unshift("4", "5");// myArray 变成了 ["4", "5", "1",
      "2", "3"]</P
    >
    <P>8.slice() 方法从数组提取一个片段，并作为一个新数组返回。</P>
    <P
      >let myArray = ["a", "b", "c", "d", "e"];myArray = myArray.slice(1, 4); // [ "b", "c", "d"]//
      从索引 1 开始，提取所有的元素，直到索引 3 为止</P
    >
    <P
      >9.at() 方法返回数组中指定索引处的元素，如果索引超出范围，则返回
      undefined。它主要用于从数组末尾访问元素的负下标。</P
    >
    <P
      >const myArray = ["a", "b", "c", "d", "e"];myArray.at(-2); // "d"，myArray 的倒数第二个元素</P
    >
    <P>10.splice() 方法从数组移除一些元素，并(可选地)替换它们。它返回从数组中删除的元素。</P>
    <P
      >const myArray = ["1", "2", "3", "4", "5"];myArray.splice(1, 3, "a", "b", "c", "d");// myArray
      现在是 ["1", "a", "b", "c", "d", "5"]// 本代码从 1 号索引开始(或元素“2”所在的位置)，// 移除 3
      个元素，然后将后续元素插入到那个位置上。</P
    >
    <P
      >11.reverse()
      方法原地颠倒数组元素的顺序：第一个数组元素变为最后一个数组元素，最后一个数组元素变为第一个数组元素。它返回对数组的引用。</P
    >
    <P
      >const myArray = ["1", "2", "3"];myArray.reverse();// 将原数组颠倒，myArray = [ "3", "2", "1"
      ]</P
    >
    <P>12.flat() 方法返回一个新数组，所有子数组元素递归地连接到其中，直到指定的深度。</P>
    <P
      >let myArray = [1, 2, [3, 4]];myArray = myArray.flat();// myArray 现在是 [1, 2, 3,
      4]，因为子数组 [3, 4] 已被展平</P
    >
    <P>13.sort() 方法对数组的元素进行适当的排序，并返回对数组的引用。</P>
    <P
      >const myArray = ["Wind", "Rain", "Fire"];myArray.sort();// 对数组排序，myArray = ["Fire",
      "Rain", "Wind"]</P
    >
    <P>14.indexOf() 方法在数组中搜索 searchElement 并返回第一个匹配的索引。</P>
    <P
      >const a = ["a", "b", "a", "b", "a"];console.log(a.indexOf("b")); // 1//
      再试一次，这次从最后一次匹配之后开始console.log(a.indexOf("b", 2)); //
      3console.log(a.indexOf("z")); // -1, 因为找不到 'z'</P
    >
    <P>15.lastIndexOf() 方法的工作原理类似于 indexOf，但这是从末尾开始，反向搜索。</P>
    <P
      >const a = ["a", "b", "c", "d", "a", "b"];console.log(a.lastIndexOf("b")); // 5//
      再试一次，这次从最后一次匹配之前开始console.log(a.lastIndexOf("b", 4)); //
      1console.log(a.lastIndexOf("z")); // -1</P
    >
    <P>16.map() 方法返回由每个数组元素上执行 callback 的返回值所组成的新数组。</P>
    <P
      >const a1 = ["a", "b", "c"];const a2 = a1.map((item) =&gt;
      item.toUpperCase());console.log(a2); // ['A', 'B', 'C']</P
    >
    <P>17.flatMap() 方法先执行 map()，再执行深度为 1 的 flat()。</P>
    <P
      >const a1 = ["a", "b", "c"];const a2 = a1.flatMap((item) =&gt; [item.toUpperCase(),
      item.toLowerCase()]);console.log(a2); // ['A', 'a', 'B', 'b', 'C', 'c']</P
    >
    <P>18.filter() 方法返回一个新数组，其中包含 callback 返回 true 的元素。</P>
    <P
      >const a1 = ["a", 10, "b", 20, "c", 30];const a2 = a1.filter((item) =&gt; typeof item ===
      "number");console.log(a2); // [10, 20, 30]</P
    >
    <P>19.find() 方法返回 callback 返回 true 的第一个元素。</P>
    <P
      >const a1 = ["a", 10, "b", 20, "c", 30];const i = a1.find((item) =&gt; typeof item ===
      "number");console.log(i); // 10</P
    >
    <P>20.findLast() 方法返回 callback 返回 true 的最后一个元素。</P>
    <P
      >const a1 = ["a", 10, "b", 20, "c", 30];const i = a1.findLast((item) =&gt; typeof item ===
      "number");console.log(i); // 30</P
    >
    <P>21.findIndex() 方法返回 callback 返回 true 的第一个元素的索引。</P>
    <P
      >const a1 = ["a", 10, "b", 20, "c", 30];const i = a1.findIndex((item) =&gt; typeof item ===
      "number");console.log(i); // 1</P
    >
    <P>22.findLastIndex() 方法返回 callback 返回 true 的最后一个元素的索引。</P>
    <P
      >const a1 = ["a", 10, "b", 20, "c", 30];const i = a1.findLastIndex((item) =&gt; typeof item
      === "number");console.log(i); // 5</P
    >
    <P>23.如果 callback 对数组中的每一个元素都返回 true，则 every() 方法返回 true。</P>
    <P
      >function isNumber(value) { return typeof value === "number";}const a1 = [1, 2,
      3];console.log(a1.every(isNumber)); // trueconst a2 = [1, "2",
      3];console.log(a2.every(isNumber)); // false</P
    >
    <P>24.如果 callback 对数组中至少一个元素返回 true，则 some() 方法返回 true。</P>
    <P
      >function isNumber(value) { return typeof value === "number";}const a1 = [1, 2,
      3];console.log(a1.some(isNumber)); // trueconst a2 = [1, "2",
      3];console.log(a2.some(isNumber)); // trueconst a3 = ["1", "2",
      "3"];console.log(a3.some(isNumber)); // false</P
    >
    <P>26.</P>
    <P
      >reduce() 方法对数组中的每个值执行 callback(accumulator, currentValue, currentIndex,
      Array)，目的是将列表中的元素减少到单个值。reduce 函数返回 callback 函数返回的最终值。</P
    >
    <P
      >如果指定了 initialValue，则调用 callback，并将 initialValue
      作为第一个参数值，将数组中第一个元素的值作为第二个参数值。</P
    >
    <P
      >如果没有指定 initialValue，那么 callback
      的前两个参数值将是数组的第一个和第二个元素。之后的每一次调用，第一个参数的值将是前一个调用中返回的
      callback，第二个参数的值将是数组中的下一个值。</P
    >
    <P>如果 callback 需要访问正在处理的元素的索引，或者访问整个数组，它们可以作为可选参数。</P>
    <P
      >const a = [10, 20, 30];const total = a.reduce( (accumulator, currentValue) =&gt; accumulator
      + currentValue, 0,);console.log(total); // 60</P
    >
    <P>27.reduceRight() 方法的工作原理类似于 reduce()，但从最后一个元素开始。</P>
    <P
      >reduce 和 reduceRight
      是迭代数组方法中最不被人熟知的两个函数。它们应该使用在那些需要把数组的元素两两递归处理，并最终计算成一个单一结果的算法。</P
    >

    <h1>详解TCP三次握手四次挥手</h1>
    <P>https://mp.weixin.qq.com/s/47lcC3LONf5IsoJHVUdxzw</P>
  </div>
</template>
<script lang="ts">
import { ref } from 'vue'
const a = ref(0)
console.log(a)
</script>

<style lang="less" scoped>
.about {
  width: 900px;
  padding: 0 100px;
  text-align: center;
  p {
    text-align: justify;
  }
}
</style>
